package cn.liccshop.core.proscenium.shopUser.service;

import cn.liccshop.core.entity.ShopUser;
import cn.liccshop.core.entity.SysUser;
import cn.liccshop.core.proscenium.shopUser.mapper.ShopUserMapper;
import cn.liccshop.core.proscenium.shopUser.service.IShopUserService;
import cn.liccshop.sys.cache.CommonCacheUtil;
import cn.liccshop.sys.constants.Constants;
import cn.liccshop.sys.entity.UserElement;
import cn.liccshop.sys.exception.MySystemException;
import cn.liccshop.sys.jms.SmsProcessor;
import cn.liccshop.sys.utils.AESUtil;
import cn.liccshop.sys.utils.RandomNumberCode;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.jms.Destination;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 消费者用户表 服务实现类
 * </p>
 *
 * @author LiCC
 * @since 2019-04-28
 */
@Service
@Slf4j
public class ShopUserServiceImpl extends ServiceImpl<ShopUserMapper, ShopUser> implements IShopUserService {

    @Autowired
    private CommonCacheUtil commonCacheUtil;
    @Autowired
    private SmsProcessor smsProcessor;

    @Override
    public ShopUser login(ShopUser shopUser) throws MySystemException {
        String token = null;
        List<ShopUser> shopUsers = list(new QueryWrapper<>(new ShopUser().setPhone(shopUser.getPhone())));
        if (CollectionUtils.isEmpty(shopUsers)){
            // 找不到用户
            throw new MySystemException("用户名或密码有误", Constants.SERVICE_FAIL);
        }
        if (shopUsers.size()>1){
            // 用户名不能同名，有多个就不能登录成功
            throw new MySystemException("用户名有误，请联系管理员",Constants.INVALID_PARM);
        }
        ShopUser shopUserOfDB = shopUsers.get(0);
        if (shopUserOfDB.getDisabled()==0){
            throw new MySystemException("该用户已被禁止登录",Constants.SERVICE_FAIL);
        }
        if (!AESUtil.encrypt(shopUser.getPassword()).equals(shopUserOfDB.getPassword())){
            // 密码匹配失败
            throw new MySystemException("用户名或密码有误",Constants.SERVICE_FAIL);
        }
        // 密码匹配成功，开始后续操作
        try {
            token =generateToken(shopUserOfDB);
        } catch (Exception e){
            log.error("生成token失败",e);
            throw new MySystemException("生成token失败");
        }
        UserElement userElement = new UserElement();
        userElement.setUserId(shopUserOfDB.getId())
                .setToken(token);
        commonCacheUtil.putTokenWhenLogin(userElement);
        shopUserOfDB.setToken(token);
        return shopUserOfDB;
    }

    @Override
    public ShopUser getUserInfo(String userId) throws MySystemException {
        ShopUser shopUser = baseMapper.selectById(userId);
        shopUser.setPassword(null);
        return shopUser;
    }

    @Override
    public boolean registerInfo(ShopUser user) throws MySystemException {
        boolean isSuccess = false;
        String code = user.getRemarks();
        user.setRemarks(null);
        /** 获取用户短信验证码 **/
        String verCode = commonCacheUtil.getCacheValue(Constants.VERIFYCODE_PREFIX + user.getPhone());
        if (code.equals(verCode)){
            /** 短信验证码匹配成功 **/
            user.setPassword(AESUtil.encrypt(user.getPassword()));
            isSuccess = retBool(baseMapper.insert(user));
        } else {
            /** 短信验证码匹配失败 **/
            throw new MySystemException("短信验证码不正确",Constants.INVALID_PARM);
        }
        return isSuccess;
    }

    @Override
    public boolean restPassword(ShopUser user) throws MySystemException {
        boolean isSuccess = false;
        String phone = user.getPhone();
        String password = user.getPassword();
        String code = user.getRemarks();
        if (StringUtils.isBlank(phone)||StringUtils.isBlank(password)||StringUtils.isBlank(code)){
            /** 手机号或密码参数有误 **/
            throw new MySystemException("参数错误", Constants.INVALID_PARM);
        }
        /** 从redis取验证码，比较手机号码和验证码是不是匹配 **/
        /** 判断用户是否在数据库是否存在，存在生成token，存redis，不存在就注册，插入数据库 **/
        String verCode = commonCacheUtil.getCacheValue(Constants.VERIFYCODE_PREFIX + phone);
        if (code.equals(verCode)){
            /** 验证码相同 **/
            user.setPassword(AESUtil.encrypt(password));
            user.setRemarks(null);
            ShopUser shopUser = baseMapper.selectOne(new QueryWrapper<>(new ShopUser().setPhone(phone)));
            shopUser.setPassword(user.getPassword());
            isSuccess = retBool(baseMapper.updateById(shopUser));
        } else {
            /** 验证码错误 **/
            throw new MySystemException("验证码不正确", Constants.INVALID_PARM);
        }
        return isSuccess;
    }

    @Override
    public void sendVercode(String mobile, String ip) throws MySystemException {
        /** 获取短信随机吗 **/
        String verCode = RandomNumberCode.getVerCode();
        int result = commonCacheUtil.cacheForVerificationCode(Constants.VERIFYCODE_PREFIX + mobile, verCode, "reg", Constants.VERCODE_CACHE_TIME, ip);
        if (result == 1){
            log.info("当前验证码未过期，请稍后重试");
            throw new MySystemException("当前验证码未过期，请稍后重试", Constants.SERVICE_FAIL);
        } else if (result == 2){
            log.info("该手机号获取验证码次数已达上限");
            throw new MySystemException("该手机号获取验证码次数已达上限", Constants.SERVICE_FAIL);
        } else if(result == 3){
            log.info("请求验证码次数已达上限", ip);
            throw new MySystemException(ip + "请求验证码次数已达上限", Constants.SERVICE_FAIL);
        }
        log.info("发送短信验证码", verCode, mobile);
        //校验已通过 发送短信 发消息到队列
        Destination destination = new ActiveMQQueue(Constants.SMS_QUEUE);
        Map<String, String> smsParam = new HashMap<>();
        smsParam.put("mobile", mobile);
        smsParam.put("tplId", Constants.MDSMS_VERCODE_TPLID);
        smsParam.put("vercode", verCode);
        String message = JSON.toJSONString(smsParam);
        smsProcessor.sendSmsToQueue(destination, message);
        //校验已通过 发送短信 发消息到队列
    }

    @Override
    public Map<String, Object> getCountGroupBySex() {
        /** 用户分类信息 **/
        List<Map<String, Object>> infosOfDB = baseMapper.getCountGroupBySex();
        /** 存储列属性 **/
        List<String> columns = new ArrayList<>();
        columns.add("性别");
        columns.add("数量");
        /** 存储数据 **/
        List<Map<String, Object>> rows = new ArrayList<>();
        Map<String, Object> secret = new HashMap<>();
        secret.put(columns.get(0), "保密");
        Map<String, Object> men = new HashMap<>();
        men.put(columns.get(0), "男");
        Map<String, Object> women = new HashMap<>();
        long allNum = 0;
        women.put(columns.get(0), "女");if (CollectionUtils.isNotEmpty(infosOfDB)){
            for(Map<String, Object> sexInfo : infosOfDB){
                if (0 == (Integer) sexInfo.get("sex")){
                    secret.put(columns.get(1), sexInfo.get("num"));
                    allNum = allNum + (long)sexInfo.get("num");
                } else if (1 == (Integer) sexInfo.get("sex")){
                    men.put(columns.get(1), sexInfo.get("num"));
                    allNum = allNum + (long)sexInfo.get("num");
                } else if (2 == (Integer) sexInfo.get("sex")){
                    women.put(columns.get(1), sexInfo.get("num"));
                    allNum = allNum + (long)sexInfo.get("num");
                }
            }
        }
        if (secret.get(columns.get(1))==null){
            secret.put(columns.get(1), 0);
        }
        if (men.get(columns.get(1))==null){
            men.put(columns.get(1), 0);
        }
        if (women.get(columns.get(1))==null){
            women.put(columns.get(1), 0);
        }
        rows.add(secret);
        rows.add(men);
        rows.add(women);
        Map<String, Object> data = new HashMap<>();
        data.put("columns", columns);
        data.put("allNum", allNum);
        data.put("rows", rows);
        return data;
    }


    /**
     * 以“用户ID + ":" + 当前时间戳”的格式生成token
     * @param user
     * @return
     */
    private String generateToken(ShopUser user) {
        String source = user.getId() + ":" + System.currentTimeMillis();
        String token = DigestUtils.md5Hex(source);
        return token;
    }
}
